/*MqttConnection的委托类，是被代理的类，
不包含一些额外的信息，
只包含最基本的业务逻辑的封装，
所有的操作方法交给代理类实现，
包括构造函数
有些需要重写的方法，要考虑交给谁去实现
*/
#ifndef MqttSubConnectionClass
#define MqttSubConnectionClass
#include "lib/mosquitto/mosquittopp.h"
#include <unordered_map>
#include <unordered_set>
#include <functional>
#include <mutex>
#include <future>
#include <vector>
#include <memory>
#include <string.h>
#include "MqttOnMessageCallback.hpp"
class MqttSubConnection : public mosqpp::mosquittopp
{
public:
    std::unordered_map<std::string, std::unordered_set<MqttOnMessageCallback *>> *topicCallbackMap; // 这个成员被保留在代理类中，而不是自己这里
    bool *connected;
    void on_message(const struct mosquitto_message *message)
    {
        // printf("onMessage\n%s\n%s\n",message->topic,message->payload);
        // 此处进行分发，注意这个struct的释放时机，如果需要其中的内容，需要把它拷贝出去，因为有些逻辑可能是异步的，不能阻塞这个连接处理其他业务
        for (auto kv : *topicCallbackMap)
        {
            bool isMatched;
            auto topicPtr = std::shared_ptr<std::string>(new std::string(message->topic));
            auto payloadPtr = std::shared_ptr<std::vector<char>>(new std::vector<char>(message->payloadlen + 1, (char)0));
            memcpy(payloadPtr.get()->data(), message->payload, message->payloadlen);
            if (mosquitto_topic_matches_sub(kv.first.c_str(), message->topic, &isMatched) == MOSQ_ERR_SUCCESS)
            {
                for (auto item : kv.second)
                {
                    // item->onMessage(topicPtr,payloadPtr);
                    std::async(std::launch::async, &MqttOnMessageCallback::onMessage, item, topicPtr, payloadPtr);
                }
            }
        }
    }
    void on_connect()
    {
        *connected = true;
        subscribeAll();
    }
    void on_disconnect()
    {
        *connected = false;
    }
    MqttSubConnection(std::unordered_map<std::string, std::unordered_set<MqttOnMessageCallback *>> *topicCallbackMap,
                      bool *connected,
                      const std::string &clientId,
                      bool cleanSession)
        : mosqpp::mosquittopp(clientId.c_str(), cleanSession)
    {
        this->topicCallbackMap = topicCallbackMap;
        this->connected = connected;
    }
    void subscribeAll()
    {
        // if (!connected)
        //     return;
        for (auto kv : *topicCallbackMap)
        {
            subscribe(NULL, kv.first.c_str());
        }
    }

    ~MqttSubConnection()
    {
    }
};
#endif